#include <nanoco.h>
#include <iostream>
#include <sys/socket.h>
#include <cstring>
#include <netinet/in.h>
#include <unistd.h>

#define EIE(e) \
    if (e)     \
    printf("错误代码：%d\n%s\n", errno, strerror(errno))

bool gQuit = false;
nco::Task<int> proread(int fd)
{
    while (1)
    {
        nco::Epoll aw{nco::eEpollIn, fd, 1000};

        co_await aw;
        if (aw.isTimeout())
        {
            cout << "fd:" << fd << " timeout \n";
            continue;
        }

        char buf[1024]{};
        size_t s = recv(fd, buf, 1024, 0);
        if (s == 0)
            break;
        for (size_t i = 0; i < s; i++)
        {
            buf[i] = std::toupper(buf[i]);
        }
        send(fd, buf, s, 0);
        if (*buf == '-')
            break;
        if(*buf == ')')
        {
            gQuit= true;
        }
    }
    close(fd);
}

nco::Task<int> co(int x)
{
    nco::Epoll aw{nco::eEpollIn, x, 10000};
to:
    aw.setTimeout(10000);
    co_await aw;
    if (aw.isTimeout())
    {
        cout << "Timeout" << endl;
        goto to;
    }
    sockaddr_in addr;
    socklen_t len;
    auto in = accept(x, (sockaddr *)&addr, &len);
    EIE(in == -1);
    proread(in);
    goto to;
}

int main()
{

    auto lfd = socket(AF_INET, SOCK_STREAM, 0);
    int opt = 1;
    setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    EIE(lfd == -1);
    sockaddr_in addr{};
    addr.sin_port = htons(2345);
    addr.sin_family = AF_INET;
    auto bindr = bind(lfd, (sockaddr *)&addr, sizeof(addr));
    EIE(bindr == -1);

    EIE(listen(lfd, 10) == -1);

    nco::EpollScheduler es;

    auto cor = co(lfd);
    while (!gQuit)
    {
        es();
    }
}